﻿using System;
using System.Collections.Generic;
using System.Data;

namespace DO.DreamOnTrader.Quote
{
	/// <summary>
	/// Tick基本類別
	/// </summary>
	public class Tick : IComparable
	{
		#region ========變數
		
		/// <summary>
		/// 成交價格
		/// </summary>
		public float Price { get { return price; } }
		private float price;
		
		/// <summary>
		/// 商品
		/// </summary>
		public Product DealProduct { get { return product; } }
		private Product product;

		/// <summary>
		/// 成交數量
		/// </summary>		
		public uint Qty { get { return qty; } }
		private uint qty;
		
		/// <summary>
		/// 成交日期
		/// </summary>
		public DateTime TradeTime { get { return tradeTime; } }
		private DateTime tradeTime;
		
		/// <summary>
		/// 交割月份 201004
		/// </summary>
		public string CloseMonth { get { return closeMonth; } }
		private string closeMonth;

		/// <summary>
		/// 需唯一的序號，排序用
		/// </summary>
		public long GuID { get { return guid; } }
		private long guid = -1;

		/// <summary>
		/// 儲存各月份最後交易時間
		/// </summary>
		static Dictionary<string, DateTime> closeDateArr = new Dictionary<string, DateTime>();

		#endregion

		/// <summary>
		/// Tick建構式
		/// </summary>
		/// <param name="_price">成交價格</param>
		/// <param name="_product">商品</param>
		/// <param name="_qty">數量</param>
		/// <param name="_tradeTime">成交時間</param>
		/// <param name="_closeMonth">交割月份</param>
		public Tick(float _price, Product _product, uint _qty, DateTime _tradeTime, string _closeMonth)
		{
			price = _price;
			product = _product;
			qty = _qty;
			tradeTime = _tradeTime;
			closeMonth = _closeMonth;
		}

		/// <summary>
		/// Tick建構式
		/// </summary>
		/// <param name="_price">成交價格</param>
		/// <param name="_product">商品</param>
		/// <param name="_qty">數量</param>
		/// <param name="_tradeTime">成交時間</param>
		/// <param name="_closeMonth">交割月份</param>
		/// <param name="id">如果要排序時，成交時間相同時會依id排序</param>
		public Tick(float _price, Product _product, uint _qty, DateTime _tradeTime, string _closeMonth, long id)
		{
			price = _price;
			product = _product;
			qty = _qty;
			tradeTime = _tradeTime;
			closeMonth = _closeMonth;
			guid = id;
		}

        /*************************************************靜態方法*************************************************/

        static Tick()
        {
            #region =======設定最後結算時間
            #region 2000
            //    closeDateArr.Add("200001", new DateTime(2000, 1, 20, 13, 45, 00));
            //    closeDateArr.Add("200002", new DateTime(2000, 2, 17, 13, 45, 00));
            //    closeDateArr.Add("200003", new DateTime(2000, 3, 16, 13, 45, 00));
            //    closeDateArr.Add("200004", new DateTime(2000, 4, 20, 13, 45, 00));
            //    closeDateArr.Add("200005", new DateTime(2000, 5, 18, 13, 45, 00));
            //    closeDateArr.Add("200006", new DateTime(2000, 6, 22, 13, 45, 00));
            //    closeDateArr.Add("200007", new DateTime(2000, 7, 20, 13, 45, 00));
            //    closeDateArr.Add("200008", new DateTime(2000, 8, 17, 13, 45, 00));
            //    closeDateArr.Add("200009", new DateTime(2000, 9, 21, 13, 45, 00));
            //    closeDateArr.Add("200010", new DateTime(2000, 10, 19, 13, 45, 00));
            //    closeDateArr.Add("200011", new DateTime(2000, 11, 16, 13, 45, 00));
            //    closeDateArr.Add("200012", new DateTime(2000, 12, 21, 13, 45, 00));
            #endregion

            #region 2001
            closeDateArr.Add("200101", new DateTime(2001, 1, 18, 13, 45, 00));
            closeDateArr.Add("200102", new DateTime(2001, 2, 22, 13, 45, 00));
            closeDateArr.Add("200103", new DateTime(2001, 3, 22, 13, 45, 00));
            closeDateArr.Add("200104", new DateTime(2001, 4, 19, 13, 45, 00));
            closeDateArr.Add("200105", new DateTime(2001, 5, 17, 13, 45, 00));
            closeDateArr.Add("200106", new DateTime(2001, 6, 21, 13, 45, 00));
            closeDateArr.Add("200107", new DateTime(2001, 7, 19, 13, 45, 00));
            closeDateArr.Add("200108", new DateTime(2001, 8, 16, 13, 45, 00));
            closeDateArr.Add("200109", new DateTime(2001, 9, 20, 13, 45, 00));
            closeDateArr.Add("200110", new DateTime(2001, 10, 18, 13, 45, 00));
            closeDateArr.Add("200111", new DateTime(2001, 11, 22, 13, 45, 00));
            closeDateArr.Add("200112", new DateTime(2001, 12, 20, 13, 45, 00));
            #endregion

            #region 2002

            closeDateArr.Add("200201", new DateTime(2002, 1, 17, 13, 45, 00));
            closeDateArr.Add("200202", new DateTime(2002, 2, 21, 13, 45, 00));
            closeDateArr.Add("200203", new DateTime(2002, 3, 21, 13, 45, 00));
            closeDateArr.Add("200204", new DateTime(2002, 4, 18, 13, 45, 00));
            closeDateArr.Add("200205", new DateTime(2002, 5, 16, 13, 45, 00));
            closeDateArr.Add("200206", new DateTime(2002, 6, 20, 13, 45, 00));
            closeDateArr.Add("200207", new DateTime(2002, 7, 18, 13, 45, 00));
            closeDateArr.Add("200208", new DateTime(2002, 8, 22, 13, 45, 00));
            closeDateArr.Add("200209", new DateTime(2002, 9, 19, 13, 45, 00));
            closeDateArr.Add("200210", new DateTime(2002, 10, 17, 13, 45, 00));
            closeDateArr.Add("200211", new DateTime(2002, 11, 21, 13, 45, 00));
            closeDateArr.Add("200212", new DateTime(2002, 12, 19, 13, 45, 00));

            #endregion

            #region 2003

            closeDateArr.Add("200301", new DateTime(2003, 1, 16, 13, 45, 00));
            closeDateArr.Add("200302", new DateTime(2003, 2, 20, 13, 45, 00));
            closeDateArr.Add("200303", new DateTime(2003, 3, 20, 13, 45, 00));
            closeDateArr.Add("200304", new DateTime(2003, 4, 17, 13, 45, 00));
            closeDateArr.Add("200305", new DateTime(2003, 5, 22, 13, 45, 00));
            closeDateArr.Add("200306", new DateTime(2003, 6, 19, 13, 45, 00));
            closeDateArr.Add("200307", new DateTime(2003, 7, 17, 13, 45, 00));
            closeDateArr.Add("200308", new DateTime(2003, 8, 21, 13, 45, 00));
            closeDateArr.Add("200309", new DateTime(2003, 9, 18, 13, 45, 00));
            closeDateArr.Add("200310", new DateTime(2003, 10, 16, 13, 45, 00));
            closeDateArr.Add("200311", new DateTime(2003, 11, 20, 13, 45, 00));
            closeDateArr.Add("200312", new DateTime(2003, 12, 18, 13, 45, 00));

            #endregion

            #region 2004

            closeDateArr.Add("200401", new DateTime(2004, 1, 28, 13, 45, 00));
            closeDateArr.Add("200402", new DateTime(2004, 2, 19, 13, 45, 00));
            closeDateArr.Add("200403", new DateTime(2004, 3, 18, 13, 45, 00));
            closeDateArr.Add("200404", new DateTime(2004, 4, 22, 13, 45, 00));
            closeDateArr.Add("200405", new DateTime(2004, 5, 20, 13, 45, 00));
            closeDateArr.Add("200406", new DateTime(2004, 6, 17, 13, 45, 00));
            closeDateArr.Add("200407", new DateTime(2004, 7, 22, 13, 45, 00));
            closeDateArr.Add("200408", new DateTime(2004, 8, 19, 13, 45, 00));
            closeDateArr.Add("200409", new DateTime(2004, 9, 16, 13, 45, 00));
            closeDateArr.Add("200410", new DateTime(2004, 10, 21, 13, 45, 00));
            closeDateArr.Add("200411", new DateTime(2004, 11, 18, 13, 45, 00));
            closeDateArr.Add("200412", new DateTime(2004, 12, 16, 13, 45, 00));

            #endregion

            #region 2005

            closeDateArr.Add("200501", new DateTime(2005, 1, 20, 13, 45, 00));
            closeDateArr.Add("200502", new DateTime(2005, 2, 17, 13, 45, 00));
            closeDateArr.Add("200503", new DateTime(2005, 3, 17, 13, 45, 00));
            closeDateArr.Add("200504", new DateTime(2005, 4, 21, 13, 45, 00));
            closeDateArr.Add("200505", new DateTime(2005, 5, 19, 13, 45, 00));
            closeDateArr.Add("200506", new DateTime(2005, 6, 16, 13, 45, 00));
            closeDateArr.Add("200507", new DateTime(2005, 7, 21, 13, 45, 00));
            closeDateArr.Add("200508", new DateTime(2005, 8, 18, 13, 45, 00));
            closeDateArr.Add("200509", new DateTime(2005, 9, 22, 13, 45, 00));
            closeDateArr.Add("200510", new DateTime(2005, 10, 20, 13, 45, 00));
            closeDateArr.Add("200511", new DateTime(2005, 11, 17, 13, 45, 00));
            closeDateArr.Add("200512", new DateTime(2005, 12, 22, 13, 45, 00));

            #endregion

            #region 2006

            closeDateArr.Add("200601", new DateTime(2006, 1, 19, 13, 45, 00));
            closeDateArr.Add("200602", new DateTime(2006, 2, 16, 13, 45, 00));
            closeDateArr.Add("200603", new DateTime(2006, 3, 16, 13, 45, 00));
            closeDateArr.Add("200604", new DateTime(2006, 4, 20, 13, 45, 00));
            closeDateArr.Add("200605", new DateTime(2006, 5, 18, 13, 45, 00));
            closeDateArr.Add("200606", new DateTime(2006, 6, 22, 13, 45, 00));
            closeDateArr.Add("200607", new DateTime(2006, 7, 20, 13, 45, 00));
            closeDateArr.Add("200608", new DateTime(2006, 8, 17, 13, 45, 00));
            closeDateArr.Add("200609", new DateTime(2006, 9, 21, 13, 45, 00));
            closeDateArr.Add("200610", new DateTime(2006, 10, 19, 13, 45, 00));
            closeDateArr.Add("200611", new DateTime(2006, 11, 16, 13, 45, 00));
            closeDateArr.Add("200612", new DateTime(2006, 12, 21, 13, 45, 00));

            #endregion

            #region 2007

            closeDateArr.Add("200701", new DateTime(2007, 1, 18, 13, 45, 00));
            closeDateArr.Add("200702", new DateTime(2007, 2, 27, 13, 45, 00));
            closeDateArr.Add("200703", new DateTime(2007, 3, 22, 13, 45, 00));
            closeDateArr.Add("200704", new DateTime(2007, 4, 19, 13, 45, 00));
            closeDateArr.Add("200705", new DateTime(2007, 5, 17, 13, 45, 00));
            closeDateArr.Add("200706", new DateTime(2007, 6, 21, 13, 45, 00));
            closeDateArr.Add("200707", new DateTime(2007, 7, 19, 13, 45, 00));
            closeDateArr.Add("200708", new DateTime(2007, 8, 16, 13, 45, 00));
            closeDateArr.Add("200709", new DateTime(2007, 9, 20, 13, 45, 00));
            closeDateArr.Add("200710", new DateTime(2007, 10, 18, 13, 45, 00));
            closeDateArr.Add("200711", new DateTime(2007, 11, 22, 13, 45, 00));
            closeDateArr.Add("200712", new DateTime(2007, 12, 20, 13, 45, 00));

            #endregion

            #region 2008

            closeDateArr.Add("200801", new DateTime(2008, 1, 17, 13, 45, 00));
            closeDateArr.Add("200802", new DateTime(2008, 2, 21, 13, 45, 00));
            closeDateArr.Add("200803", new DateTime(2008, 3, 20, 13, 45, 00));
            closeDateArr.Add("200804", new DateTime(2008, 4, 17, 13, 45, 00));
            closeDateArr.Add("200805", new DateTime(2008, 5, 22, 13, 45, 00));
            closeDateArr.Add("200806", new DateTime(2008, 6, 19, 13, 45, 00));
            closeDateArr.Add("200807", new DateTime(2008, 7, 17, 13, 45, 00));
            closeDateArr.Add("200808", new DateTime(2008, 8, 21, 13, 45, 00));
            closeDateArr.Add("200809", new DateTime(2008, 9, 18, 13, 45, 00));
            closeDateArr.Add("200810", new DateTime(2008, 10, 16, 13, 45, 00));
            closeDateArr.Add("200811", new DateTime(2008, 11, 20, 13, 45, 00));
            closeDateArr.Add("200812", new DateTime(2008, 12, 17, 13, 30, 00));

            #endregion

            #region 2009

            closeDateArr.Add("200901", new DateTime(2009, 1, 21, 13, 30, 00));
            closeDateArr.Add("200902", new DateTime(2009, 2, 18, 13, 30, 00));
            closeDateArr.Add("200903", new DateTime(2009, 3, 18, 13, 30, 00));
            closeDateArr.Add("200904", new DateTime(2009, 4, 15, 13, 30, 00));
            closeDateArr.Add("200905", new DateTime(2009, 5, 20, 13, 30, 00));
            closeDateArr.Add("200906", new DateTime(2009, 6, 17, 13, 30, 00));
            closeDateArr.Add("200907", new DateTime(2009, 7, 15, 13, 30, 00));
            closeDateArr.Add("200908", new DateTime(2009, 8, 19, 13, 30, 00));
            closeDateArr.Add("200909", new DateTime(2009, 9, 16, 13, 30, 00));
            closeDateArr.Add("200910", new DateTime(2009, 10, 21, 13, 30, 00));
            closeDateArr.Add("200911", new DateTime(2009, 11, 18, 13, 30, 00));
            closeDateArr.Add("200912", new DateTime(2009, 12, 16, 13, 30, 00));

            #endregion

            #region 2010

            closeDateArr.Add("201001", new DateTime(2010, 1, 20, 13, 30, 00));
            closeDateArr.Add("201002", new DateTime(2010, 2, 22, 13, 30, 00));
            closeDateArr.Add("201003", new DateTime(2010, 3, 17, 13, 30, 00));
            closeDateArr.Add("201004", new DateTime(2010, 4, 21, 13, 30, 00));
            closeDateArr.Add("201005", new DateTime(2010, 5, 19, 13, 30, 00));
            closeDateArr.Add("201006", new DateTime(2010, 6, 17, 13, 30, 00));
            closeDateArr.Add("201007", new DateTime(2010, 7, 21, 13, 30, 00));
            closeDateArr.Add("201008", new DateTime(2010, 8, 18, 13, 30, 00));
            closeDateArr.Add("201009", new DateTime(2010, 9, 15, 13, 30, 00));
            closeDateArr.Add("201010", new DateTime(2010, 10, 20, 13, 30, 00));
            closeDateArr.Add("201011", new DateTime(2010, 11, 17, 13, 30, 00));
            closeDateArr.Add("201012", new DateTime(2010, 12, 15, 13, 30, 00));

            #endregion

            #region 2011

            closeDateArr.Add("201101", new DateTime(2011, 1, 19, 13, 30, 00));
            closeDateArr.Add("201102", new DateTime(2011, 2, 16, 13, 30, 00));
            closeDateArr.Add("201103", new DateTime(2011, 3, 16, 13, 30, 00));
            closeDateArr.Add("201104", new DateTime(2011, 4, 20, 13, 30, 00));
            closeDateArr.Add("201105", new DateTime(2011, 5, 18, 13, 30, 00));
            closeDateArr.Add("201106", new DateTime(2011, 6, 15, 13, 30, 00));
            closeDateArr.Add("201107", new DateTime(2011, 7, 20, 13, 30, 00));
            closeDateArr.Add("201108", new DateTime(2011, 8, 17, 13, 30, 00));
            closeDateArr.Add("201109", new DateTime(2011, 9, 21, 13, 30, 00));
            closeDateArr.Add("201110", new DateTime(2011, 10, 19, 13, 30, 00));
            closeDateArr.Add("201111", new DateTime(2011, 11, 16, 13, 30, 00));
            closeDateArr.Add("201112", new DateTime(2011, 12, 21, 13, 30, 00));

            #endregion

            #endregion
        }

        /// <summary>
        /// 取得此商品月份最後交易時間
        /// </summary>
        /// <param name="key">ex: 201108</param>
        /// <returns>DateTime 最後交易時間</returns>
        public static DateTime getCloseDate(string key)
        {
            if (closeDateArr.ContainsKey(key))
            {
                return closeDateArr[key];
            }
            else
            {
                DateTime _d = new DateTime(int.Parse(key.Substring(0, 4)), int.Parse(key.Substring(4)), 1, 13, 30, 0);
                while (_d.DayOfWeek != DayOfWeek.Wednesday)
                {
                    _d = _d.AddDays(1);
                }
                _d = _d.AddDays(14);

                return _d;
            }
        }

		/// <summary>
		/// 取得此商品月份最後交易時間
		/// </summary>
		/// <param name="time"></param>
		/// <returns>DateTime 最後交易時間</returns>
		public static DateTime getCloseDate(DateTime time)
		{
			DateTime _lastTradeTime = Tick.getCloseDate(time.Year.ToString() + time.Month.ToString().PadLeft(2, '0'));

			if (time > _lastTradeTime)
			{
				_lastTradeTime = time.AddMonths(1);
				return Tick.getCloseDate(_lastTradeTime.Year.ToString() + _lastTradeTime.Month.ToString().PadLeft(2, '0'));
			}
			else
			{
				return _lastTradeTime;
			}
		}

        /**********************************************************************************************************/

		public override string ToString()
		{
			string[] nn = { tradeTime.ToString("yyyy/MM/dd hh:mm:ss"), product.ToString(), "商品月份 " + closeMonth, "成交價格:" + price.ToString(), "成交量:" + qty.ToString(), "tempid " + guid.ToString() };
			return string.Join(",", nn);
		}

		#region IComparable 成員

		public int CompareTo(object obj)
		{
			Tick tobj = (Tick)obj;
			if (this.tradeTime.CompareTo(tobj.tradeTime) == 0)
			{
				return this.guid.CompareTo(tobj.guid);
			}
			else
			{
				return this.tradeTime.CompareTo(tobj.tradeTime);
			}
		}

		#endregion
	}
}
